
import Database from 'better-sqlite3';
import path from "path";
type FieldType = 'string' | 'number' | 'boolean' | 'date';

interface FieldDefinition {
  type: FieldType;
  primaryKey?: boolean;
  autoIncrement?: boolean;
  allowNull?: boolean;
  unique?: boolean;
}

export interface ModelDefinition {
  [key: string]: FieldDefinition;
}

export class Model  {
  protected static db: Database.Database;
  protected static tableName: string;
  protected static fields: ModelDefinition;

  static connect(dbPath: string) {
    this.db = new Database(dbPath);
  }

  static init(fields: ModelDefinition) {

    this.fields = fields;
    this.tableName = this.name.toLowerCase();
    
    // 构建创建表的 SQL
    const fieldDefinitions = Object.entries(fields).map(([fieldName, definition]) => {
      const parts = [fieldName];
      
      switch (definition.type) {
        case 'string':
          parts.push('TEXT');
          break;
        case 'number':
          parts.push('INTEGER');
          break;
        case 'boolean':
          parts.push('BOOLEAN');
          break;
        case 'date':
          parts.push('DATETIME');
          break;
      }

      if (definition.primaryKey) {
        parts.push('PRIMARY KEY');
      }
      if (definition.autoIncrement) {
        parts.push('AUTOINCREMENT');
      }
      if (!definition.allowNull) {
        parts.push('NOT NULL');
      }
      if (definition.unique) {
        parts.push('UNIQUE');
      }

      return parts.join(' ');
    });

    const createTableSQL = `
      CREATE TABLE IF NOT EXISTS ${this.tableName} (
        ${fieldDefinitions.join(',\n        ')}
      )
    `;

    try {
      this.db.prepare(createTableSQL).run();
    } catch (error) {
      console.error('Error creating table:', error);
      throw error;
    }
  }

  // 基础的 CRUD 方法
  static create(data: Record<string, any>) {
    const fields = Object.keys(data).join(', ');
    const placeholders = Object.keys(data).map(() => '?').join(', ');
    const sql = `INSERT INTO ${this.tableName} (${fields}) VALUES (${placeholders})`;
    
    try {
      const stmt = this.db.prepare(sql);
      return stmt.run(Object.values(data));
    } catch (error) {
      console.error('Error creating record:', error);
      throw error;
    }
  }
    // Update records based on conditions
    static update(where: Record<string, any>, data: Record<string, any>) {
      const setClause = Object.entries(data).map(([key]) => `${key} = ?`).join(', ');
      const conditions = Object.entries(where).map(([key]) => `${key} = ?`).join(' AND ');
      const sql = `UPDATE ${this.tableName} SET ${setClause} WHERE ${conditions}`;
  
      try {
        const stmt = this.db.prepare(sql);
        return stmt.run([...Object.values(data), ...Object.values(where)]);
      } catch (error) {
        console.error('Error updating record:', error);
        throw error;
      }
    }
  
  static findOne(where: Record<string, any>){
    const conditions = Object.entries(where).map(([key]) => `${key} = ?`).join(' AND ');
    const sql = `SELECT * FROM ${this.tableName} WHERE ${conditions} LIMIT 1`;
    
    try {
      const stmt = this.db.prepare(sql);
      return stmt.get(Object.values(where))  ;
    } catch (error) {
      console.error('Error finding record:', error);
      throw error;
    }
  }

  static findAll <O extends typeof Model>(this:O, where: Record<string, any> = {}):InstanceType<O>[] {
    let sql = `SELECT * FROM ${this.tableName}`;
    const values: any[] = [];
    
    if (Object.keys(where).length > 0) {
      const conditions = Object.entries(where).map(([key]) => `${key} = ?`).join(' AND ');
      sql += ` WHERE ${conditions}`;
      values.push(...Object.values(where));
      
    }
    
    try {
      const stmt = this.db.prepare(sql);
      return stmt.all(values)  as   InstanceType<O>[]   ;
    } catch (error) {
      console.error('Error finding records:', error);
      throw error;
    }
  }
  static delete(where: Record<string, any>) {
    const conditions = Object.entries(where).map(([key]) => `${key} = ?`).join(' AND ');
    const sql = `DELETE FROM ${this.tableName} WHERE ${conditions}`;
    
    try {
      const stmt = this.db.prepare(sql);
      return stmt.run(Object.values(where));
    } catch (error) {
      console.error('Error deleting record:', error);
      throw error;
    }
  }
}

Model.connect(path.resolve(process.cwd(),"db.database"));